using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Threading;
using System.Diagnostics;
using System.Collections;
using System.Runtime.Serialization;
using System.Runtime.Versioning;
using System.Net.Sockets;
using BrainTechLLC;

namespace Mud.EmlenMudMain
{
    [Serializable]
    public class OldSchoolAreas
    {

        public OldSchoolAreas() { }

        public void load_old_area_format(StreamReader sr, ref AreaData pArea)
        {
            char[] spc = " ".ToCharArray();
            char[] tilde = "~".ToCharArray();
            pArea.RepopCountdownMinutes = EmlenMud.RandIntBetween(30, 55);
            pArea.RepopCountdownMinutes = 1;

            while (sr.EndOfStream == false)
            {
                string szLine = sr.ReadLine().Trim();
                if (szLine == "End")
                {
                    break;
                }
                string[] rgsz = szLine.Split(spc, 2, StringSplitOptions.RemoveEmptyEntries);
                string szWord = rgsz[0];
                if (szWord == "Name")
                {
                    pArea.Name = new NameAndDescription() { Name = rgsz[1].TrimEnd(tilde), FriendlyUniqueName = rgsz[1].TrimEnd(tilde) };
                    continue;
                }
                if (szWord == "NQuit")
                {
                    pArea.PreventPlayersQuittingInArea = Convert.ToInt32(rgsz[1]);
                    continue;
                }
                if (szWord == "Security")
                {
                    pArea.Security = Convert.ToInt32(rgsz[1]);
                    continue;
                }
                if (szWord == "SRepop")
                {
                    pArea.RepopRateInMinutes = Convert.ToInt32(rgsz[1]);
                    continue;
                }

                if (szWord == "SJail")
                {
                    pArea.RoomVnumForJail = Convert.ToInt32(rgsz[1]);
                    continue;
                }
                if (szWord == "SCZone") { pArea.Clanzone = Convert.ToInt32(rgsz[1]); continue; }
                if (szWord == "SOutJail") { pArea.RoomVnumExitsJailTo = Convert.ToInt32(rgsz[1]); continue; }
                if (szWord == "VNUMs")
                {
                    string[] rgSpl2 = rgsz[1].Split(spc, 2, StringSplitOptions.RemoveEmptyEntries);
                    pArea.LowestVnumBelongingToArea = Convert.ToInt32(rgSpl2[0]);
                    pArea.HighestVnumBelongingToArea = Convert.ToInt32(rgSpl2[1]);
                    continue;
                }

                if (szWord == "Builders")
                {
                    string[] rgSpl3 = rgsz[1].Split(spc, StringSplitOptions.RemoveEmptyEntries);
                    for (int j = 0; j < rgSpl3.Length; j++)
                    {
                        pArea.Builders.Add(rgSpl3[j].TrimEnd('~'));
                    }
                    continue;
                }
                if (szWord == "Open") { pArea.OpenToPlayers = Convert.ToInt32(rgsz[1]); continue; }
                if (szWord == "Rcount") { pArea.NumberOfRoomsInArea = Convert.ToInt32(rgsz[1]); continue; }
                if (szWord == "Repop") { pArea.RepopMessage = rgsz[1].TrimEnd('~'); continue; }
                if (szWord == "Reset") { continue; }  // ?????
            }
            pArea.RepopCountdownMinutes = Rand.RandIntBetween(1, pArea.RepopRateInMinutes);
        }

        public void save_old_area_format(System.IO.StreamWriter sw, AreaData pArea)
        {
            sw.WriteLine("Name " + pArea.Name + "~");
            sw.WriteLine("NQuit " + pArea.PreventPlayersQuittingInArea.ToString());
            sw.WriteLine("Security " + pArea.Security.ToString());
            sw.WriteLine("SRepop " + pArea.RepopRateInMinutes.ToString());
            sw.WriteLine("SJail " + pArea.RoomVnumForJail.ToString());
            sw.WriteLine("SCZone " + pArea.Clanzone.ToString());
            sw.WriteLine("SOutJail " + pArea.RoomVnumExitsJailTo.ToString());
            sw.WriteLine("VNUMs " + pArea.LowestVnumBelongingToArea.ToString() + " " + pArea.HighestVnumBelongingToArea.ToString());
            sw.Write("Builders");
            for (int n = 0; n < pArea.Builders.Count; n++)
            {
                string sz = (string)pArea.Builders[n];
                sw.Write(" " + sz);
            }
            sw.WriteLine("~");
            sw.WriteLine("Open " + pArea.OpenToPlayers.ToString());
            sw.WriteLine("Rcount " + pArea.NumberOfRoomsInArea.ToString());
            sw.WriteLine("Repop " + pArea.RepopMessage + "~");
            // sw.WriteLine("Reset " + ?????);
            sw.WriteLine("End");
            sw.WriteLine("");
        }


        public AreaData LoadSingleArea(string szFullPathAndFileName, OldSchoolRooms osRooms,
          OldSchoolMobPrototyes osMP, OldSchoolObjPrototypes osOP)
        {
            FileStream fsArea = null;
            try
            {
                fsArea = new FileStream(szFullPathAndFileName, FileMode.Open, FileAccess.Read);
            }
            catch (IOException ex)
            {
                Debug.WriteLine("LoadSingleArea: " + ex.Message);
                return null;
            }
            StreamReader srArea = new StreamReader(fsArea);
            AreaData area = (AreaData)LoadSingleArea(srArea, osRooms, osMP, osOP);
            srArea.Close();
            fsArea.Close();
            return area;
        }

        public AreaData LoadSingleArea(StreamReader srArea, OldSchoolRooms osRooms,
          OldSchoolMobPrototyes osMP, OldSchoolObjPrototypes osOP)
        {
            return LoadSingleArea(srArea, "", osRooms, osMP, osOP);
        }

        public AreaData LoadSingleArea(StreamReader srArea, string szArea, OldSchoolRooms osRooms,
          OldSchoolMobPrototyes osMP, OldSchoolObjPrototypes osOP)
        {
            AreaData area = null;
            try
            {
                while (srArea.EndOfStream == false)
                {
                    char c = ' ';
                    while (c != '#' && srArea.EndOfStream == false) c = (char)srArea.Read();
                    if (c != '#')
                    {
                        EmlenMud.LogError("Area " + szArea + " possibly corrupt?  No #...", null, LogType.WorldError);
                        break;
                    }
                    string szSection = srArea.ReadLine().Trim();

                    if (area == null)
                    {
                        area = new AreaData();
                        area.Name = new NameAndDescription() { Name = szArea, FriendlyUniqueName = szArea };
                    }

                    if (szSection[0] == '$')
                    {
                        EmlenMud.OutputMessage("Area " + szArea + " loaded successfully!");
                        area.AreaFileName = szArea;
                        area.RepopCountdownMinutes = Rand.RandIntBetween(1, area.RepopRateInMinutes);
                        EmlenMud.WorldTemplates.AllAreas.Add(area);
                        EmlenMud.WorldTemplates.nAreaCount++;
                        if (area.OpenToPlayers != 0) EmlenMud.WorldTemplates.open_areas++;
                        EmlenMud.WorldTemplates.AllAreas.Sort(new Comparison<AreaData>((a, b) => a.LowestVnumBelongingToArea.CompareTo(b.LowestVnumBelongingToArea)));
                        break;
                    }
                    else if (szSection == "HELPS")
                    {
                        //if (EmlenMud == null) return null;
                        HelpData.load_old_style_helps(srArea);
                    }
                    else if (szSection == "AREADATA")
                    {
                        AreaData areaI = (AreaData)area;
                        load_old_area_format(srArea, ref areaI);
                    }
                    else if (szSection == "MOBDATA")
                    {
                        osMP.load_mobiles_old_format(srArea, area);
                    }
                    else if (szSection == "OBJDATA")
                    {
                        osOP.load_objects_old_format(srArea, area);
                    }
                    else if (szSection == "ROOMDATA")
                    {
                        osRooms.load_rooms_old_format(srArea, area);
                    }
                    else
                    {
                        EmlenMud.LogError("Area " + szArea + " had bad section name: " + szSection, null, LogType.WorldError);
                    }
                }
            }
            catch (Exception ex)
            {
#if NO_SILVERLIGHT
                GlobalLogger.Log(ex, BrainTechLLC.ThreadSafeObjects.LogSeverity.Error, true);
#endif
            }
            return area;
        }

        public void LoadOldFormatAreasMobsObjectsEtc(string szAreaList)
        {
            for (int i = 0; i < EmlenMud.WorldTemplates.arealist.AreaFileNames.Count; i++)
            {
                string szArea = (string)EmlenMud.WorldTemplates.arealist.AreaFileNames[i];
                if (szArea == "$") break;
                FileStream fsArea = null;
                string szFullPathAndFileName = szAreaList + szArea;
                try
                {
                    fsArea = new FileStream(szFullPathAndFileName, FileMode.Open, FileAccess.Read);
                }
                catch (IOException ex)
                {
                    EmlenMud.LogError("Error finding area file " + szFullPathAndFileName + " : ", ex, LogType.Always);
                    continue;
                }

                StreamReader srArea = new StreamReader(fsArea);
                AreaData area = (AreaData)LoadSingleArea(srArea, szArea, EmlenMud.OldschoolRoom,
                  EmlenMud.OldschoolMP, EmlenMud.OldschoolOP);
                srArea.Close();
                fsArea.Close();
                if (area != null) area.OriginalFileName = szFullPathAndFileName;
            }
        }

        public void SaveSingleArea(StreamWriter sw, AreaData area,
          OldSchoolRooms osRooms, OldSchoolMobPrototyes osMP, OldSchoolObjPrototypes osOP)
        {
            sw.WriteLine("#AREADATA");
            save_old_area_format(sw, area);
            sw.WriteLine("");

            sw.WriteLine("#MOBDATA");
            for (int n = 0; n < area.MobPrototypesBelongingToArea.Count; n++)
            {
                MobPrototype mp = (MobPrototype)area.MobPrototypesBelongingToArea[n];
                osMP.WriteOldMobileFormat(sw, mp.Vnum, mp, area);
            }
            sw.WriteLine("#0");
            sw.WriteLine("");

            sw.WriteLine("#OBJDATA");
            for (int n = 0; n < area.ObjectPrototypesBelongingToArea.Count; n++)
            {
                ObjectPrototype op = (ObjectPrototype)area.ObjectPrototypesBelongingToArea[n];
                osOP.WriteOldObjectFormat(sw, op.Vnum, op, area);
            }
            sw.WriteLine("#0");
            sw.WriteLine("");

            sw.WriteLine("#ROOMDATA");
            for (int n = 0; n < area.RoomsInArea.Count; n++)
            {
                RoomData room = (RoomData)area.RoomsInArea[n];
                osRooms.WriteOldRoomFormat(sw, room.VnumRoom, room, area);
            }
            sw.WriteLine("#0");
            sw.WriteLine("");
            sw.WriteLine("#$");
        }

        public void SaveOldFormatAreasMobsObjectsEtc(string szAreaList)
        {
            for (int i = 0; i < EmlenMud.WorldTemplates.arealist.AreaFileNames.Count; i++)
            {
                string szArea = (string)EmlenMud.WorldTemplates.arealist.AreaFileNames[i];
                if (szArea == "$") break;
                AreaData area = EmlenMud.WorldTemplates.FindArea(szArea);
                if (area == null)
                {
                    EmlenMud.LogError("Could not find area " + szArea + " in memory!", null, LogType.Always | LogType.WorldError);
                    continue;
                }
                FileStream fsArea = null;
                try
                {
                    fsArea = new FileStream(szAreaList + szArea, FileMode.Create, FileAccess.Write);
                }
                catch (IOException ex)
                {
                    EmlenMud.LogError("Error creating area " + szAreaList + szArea + " : ", ex, LogType.Always);
                    continue;
                }

                StreamWriter sw = new StreamWriter(fsArea);
                SaveSingleArea(sw, area, EmlenMud.OldschoolRoom,
                  EmlenMud.OldschoolMP, EmlenMud.OldschoolOP);
                sw.Flush();
                sw.Close();
                fsArea.Close();
            }
        }
    }
}
